package com.jian.mygame;


import java.util.ArrayList;

import org.jbox2d.collision.AABB;
import org.jbox2d.collision.CircleDef;
import org.jbox2d.collision.PolygonDef;

import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.World;

import android.content.Context;
import android.util.Log;


class MyWorld extends Object {
	final static int RATE = 100;
	private AABB worldAABB;
	private World world;
	private float timeStep = 1/60;
	private int iterations = 10;
	
	MyContactListener mContactListner;
    private final float GRAVITY = 10.0f; 
    
	static public enum WorldDirection{
		LEFT, RIGHT, UP, DOWN		
	};

	public void CreateWorld(Context context) {
	    worldAABB = new AABB();
	    
	    worldAABB.lowerBound.set(-10.0f,-10.0f);
	    worldAABB.upperBound.set(10.0f, 10.0f);
	    
	    Vec2 gravity = new Vec2(0.0f,10.0f);
	    boolean doSleep = true;

	    world = new World(worldAABB, gravity, doSleep);
	    mContactListner = new MyContactListener();
	    world.setContactListener(mContactListner);
	    
	    //setContext(context);
	    
	    timeStep = 1.0f/60.0f;
	    //timeStep = 1.0f/30.0f;
	    iterations = 10;
	}
	
	public void setGravity( float x, float y ){
		Vec2 curGravity = world.getGravity();
		
		if( x != curGravity.x || y != curGravity.y ) {
			world.setGravity(new Vec2(x, y));
			
			//If Gravity changes, wakeup sleeping body
			for (Body body = world.getBodyList(); body != null; body = body.getNext()) {
				if( body.isSleeping() && body.isStatic() == false ) {
					body.wakeUp();
				}
			}
		}
	}
	
	public void setGravity( WorldDirection  dir ){
		
		switch(dir) {
		case LEFT:
			world.setGravity(new Vec2(-GRAVITY,0));
			break;
		case RIGHT:
			world.setGravity(new Vec2(GRAVITY,0));
			break;
		case UP:
			world.setGravity(new Vec2(0,-GRAVITY));
			break;
		case DOWN:
			world.setGravity(new Vec2(0,GRAVITY));
			break;
		default:
			break;
		}
	}
	
	public int getBodyCount(){
		return world.getBodyCount();
	}
	
	public void destroyBody(Body body){
		world.destroyBody(body);
	}
	
	public Body getBodyList( ){
		return world.getBodyList();
	}
		
    public Body createBox(float x,float y, float half_width, float half_height, float angle, 
    		              float density, float friction, float restitution, boolean isStatic,
    		              BodyExtend bodyextend ){ 
    	Body body;
    	PolygonDef shape = new PolygonDef();
    	
		if(isStatic){
			shape.density = 0.0f;
		} else { 
			shape.density = density;
		}
		shape.friction = friction;
		shape.restitution = restitution;
		shape.setAsBox(half_width/RATE, half_height/RATE);
		
		BodyDef bodyDef = new BodyDef();
		bodyDef.position.set(x/RATE, y/RATE);
		bodyDef.angle = angle;//(float) (degree*Math.PI/180);
		body = (Body) world.createBody(bodyDef);
		body.createShape(shape);
		body.setMassFromShapes();
		
		//Link BodyExtend to Body
		body.setUserData(bodyextend);
		
		return body;
    }
    
    public Body createCircle(float x,float y, float radius, float angle, 
                             float density, float friction, float restitution, boolean isStatic,
                             BodyExtend bodyextend ){
    	Body body;
		CircleDef shape = new CircleDef();
		
		if(isStatic){
			shape.density = 0.0f;
		} else { 
			shape.density = density;
		}
		shape.friction = friction;
		shape.restitution = restitution;
		shape.radius = radius/RATE;
		
		BodyDef bodyDef = new BodyDef();
		bodyDef.position.set(x/RATE, y/RATE);
		body = (Body) world.createBody(bodyDef);
		body.createShape(shape);
		body.setMassFromShapes();
		
		//Link BodyExtend to Body
		body.setUserData(bodyextend);
		
		return body;
	}
    
    
    protected Body createSimpleBoxCenter(float x,float y,float half_width,float half_height, float angle, 
    									 float density, float friction, float restitution,
    									 int colorIdx, boolean isDrawable, boolean isStatic, int role,
    									 BodyExtend bodyextend ){ 
		Body body;
		PolygonDef shape = new PolygonDef();
		if(isStatic){
			shape.density = 0.0f;
		}else{
			shape.density = density;
		}
		shape.friction = friction;
		shape.restitution = restitution;
		shape.setAsBox(half_width/RATE, half_height/RATE);
		
		BodyDef bodyDef = new BodyDef();
		bodyDef.position.set(x/RATE, y/RATE);
		bodyDef.angle = angle;
		body = (Body) world.createBody(bodyDef);
		body.createShape(shape);
		body.setMassFromShapes();
		
		//Link BodyExtend to Body
		body.setUserData(bodyextend);
		
		return body;
	}
    
    protected Body createPolygon(Vec2[] vec, float x, float y, float angle,
    		                     float density, float friction, float restitution,
	  		                     int colorIdx, boolean isDrawable, boolean isStatic, int role,
	  		                     BodyExtend bodyextend ){ 
		Body body;
		PolygonDef shape = new PolygonDef();
		if(isStatic){
			shape.density = 0.0f;
		}else{
			shape.density = density;
		}
		shape.friction = friction;
		shape.restitution = restitution;

		//Filter Vertex
		//Vec2[] newVec = filterVertex(vec);
		//Log.d("MyWorld", "newVec[].size: " + newVec.length);
		for( Vec2 v: vec){
			Log.d("MyWorld", "newVec[] x: " + v.x + " /y: " + v.y);
			shape.addVertex(new Vec2(v.x/RATE, v.y/RATE));
		}
		
		BodyDef bodyDef = new BodyDef();
		bodyDef.position.set(x/RATE, y/RATE);
		bodyDef.angle = angle;
		body = (Body) world.createBody(bodyDef);
		body.createShape(shape);
		body.setMassFromShapes();

		//Link BodyExtend to Body
		body.setUserData(bodyextend);
		
		return body;
	}
        
	public void updateWorld() {
		world.step(timeStep, iterations);
		//Log.d("MyWorld", "Gravity: x: " + world.getGravity().x + " / y: " + world.getGravity().y);
	}

	/*
	public void addNewBird( int random_num ) {
		Body body = null;
		Random rnd = new Random();
		int size = MyFactory.mTargetRes.length;
		int type = random_num%size;
        int x = 100+rnd.nextInt(400);
        //body = createBody(x, 0.0f, 0.0f, MyFactory.mTargetRes[type], null, BodyExtend.ROLE_TARGET, false );
        body = createBody(490, 250.0f, 0.0f, MyFactory.mTargetRes[type], null, BodyExtend.ROLE_TARGET, false );
        
        //double angle = (50 + rnd.nextInt(50))* Math.PI / 100;
        double angle = - Math.PI *3 / 4;
        Vec2 vec = new Vec2((float)(20*2000.0f*Math.cos(angle)),
	    		            (float)(20*1800.0f*Math.sin(angle)) 
	                       ); 
        body.applyForce( vec , body.getPosition());
        
//        int soundid = ((BodyExtend)(body.getUserData())).getSoundID();
//        if (soundid == 0) {
//        	assert(false);
//        }
	}
	*/
	
    /*
    public Body createCircle(float x,float y,float radius, int colorIdx){
    	Body body;
    	BodyExtend bodyextend;
		CircleDef shape = new CircleDef();
		shape.density = 4f;
		shape.friction = 0.2f;
		shape.radius = radius/RATE;
		
		BodyDef bodyDef = new BodyDef();
		bodyDef.position.set(x/RATE, y/RATE);
		body = (Body) world.createBody(bodyDef);
		body.createShape(shape);
		body.setMassFromShapes();
		
		bodyextend = new BodyExtend();
		bodyextend.setColor(colorIdx);
		body.setUserData(bodyextend);
		mBodyList.add(body);
		
		return mBodyList.get(mBodyList.indexOf(body));
	}
	*/
 	
	/*
	public void setCanvas( Canvas canvas ) {
		mCanvas = canvas;
		mContactListner.setCanvas(canvas);
	}
	*/
	
    
    /*
     * To Be Removed
    private BodyExtend createBodyExtend( ResourceInfo tool, AnimationInfo anima_info , int role ) {
		BodyExtend bodyextend = new BodyExtend();
    	Resources res = mContext.getResources();
        int imageID = tool.mImageID;
    	Drawable image = res.getDrawable(imageID);
		
		//bodyextend.setColor(colorIdx);
		bodyextend.setImage(image);
		
		if( anima_info != null){
	        MyAnimation anima = new MyAnimation();
	        anima.Initialize(
							BitmapFactory.decodeResource(res, anima_info.mResID), 
							anima_info.mHeight, anima_info.mWidth, anima_info.mFps, anima_info.mFrameCount);
			bodyextend.setAnimation(anima);
		}
		
		bodyextend.setSoundID(tool.mSoundID); 
		bodyextend.setRole(role);
		
		return bodyextend;
    }
    */
}
